
#include "drv_api.h"

#include "usw/include/drv_common.h"
#include "usw/include/drv_ftm.h"

int32
drv_usw_ftm_get_entry_num(uint8 lchip, uint32 tbl_id, uint32* entry_num)
{
    DRV_INIT_CHECK(lchip);
    *entry_num = TABLE_MAX_INDEX(lchip, tbl_id);

    if ((MEM_TYPE_PEER_DP == TABLE_ENTRY_TYPE(lchip, tbl_id) || MEM_TYPE_PEER_PP == TABLE_ENTRY_TYPE(lchip, tbl_id))
        && (drv_vchip_get_core_num(lchip) < 2))
    {
        /*sigle core mode*/
        *entry_num /= 2;
    }

    return DRV_E_NONE;
}


int32
drv_ftm_get_tbl_detail(uint8 lchip, drv_ftm_tbl_detail_t* p_tbl_info)
{
    DRV_PTR_VALID_CHECK(p_tbl_info);

    switch(p_tbl_info->type)
    {
    case DRV_FTM_TBL_TYPE:
        DRV_TBL_ID_VALID_CHECK(lchip, p_tbl_info->tbl_id);
        if (NULL == TABLE_EXT_INFO_PTR(lchip, p_tbl_info->tbl_id) || (TABLE_EXT_TYPE(lchip, p_tbl_info->tbl_id) == 1))
        {
            p_tbl_info->tbl_type = DRV_FTM_TABLE_STATIC;
            return 0;
        }

        switch(TABLE_EXT_INFO_TYPE(lchip, p_tbl_info->tbl_id))
        {
        case EXT_INFO_TYPE_TCAM:
        case EXT_INFO_TYPE_STATIC_TCAM_KEY:
        case EXT_INFO_TYPE_LPM_TCAM_IP:
        case EXT_INFO_TYPE_LPM_TCAM_NAT:
            p_tbl_info->tbl_type = DRV_FTM_TABLE_TCAM_KEY;

            break;

        default:
            p_tbl_info->tbl_type = DRV_FTM_TABLE_DYNAMIC;
        }

        break;

    default:
        return DRV_E_INVAILD_TYPE;
    }

    return 0;
}



/*------------------------------------------------------------
*    MCHIP API
-------------------------------------------------------------*/

int32
drv_usw_ftm_set_hash_poly(uint8 lchip, uint32 mem_id, uint8 sram_type, uint32 drv_poly)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_set_hash_poly)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_set_hash_poly(lchip, mem_id, sram_type, drv_poly);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_hash_poly(uint8 lchip, uint32 mem_id, uint8 sram_type, uint32* drv_poly)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_hash_poly)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_hash_poly(lchip, mem_id, sram_type, drv_poly);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_show_hash_poly(uint8 lchip, uint32 mem_id, uint8 sram_type)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_show_hash_poly)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_show_hash_poly(lchip, mem_id, sram_type);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_lookup_ctl_init(uint8 lchip)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_lookup_ctl_init)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_lookup_ctl_init(lchip);
    }

    return DRV_E_NONE;
}


int32
drv_usw_ftm_mem_alloc(uint8 lchip, void* p_profile_info)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_mem_alloc)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_mem_alloc(lchip, p_profile_info);
    }

    return DRV_E_NONE;
}


int32
drv_usw_ftm_mem_free(uint8 lchip)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_mem_free)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_mem_free(lchip);
    }

    return DRV_E_NONE;
}


int32
drv_usw_ftm_get_info_detail(uint8 lchip, drv_ftm_info_detail_t* p_ftm_info)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_info_detail)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_info_detail(lchip, p_ftm_info);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_sram_type(uint8 lchip, uint32 mem_id, uint8* p_sram_type)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_sram_type)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_sram_type(lchip, mem_id, p_sram_type);
    }

    return DRV_E_NONE;
}

int32
drv_ftm_get_mem_info(uint8 lchip, drv_ftm_mem_info_t* p_mem_info)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_mem_info)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_mem_info(lchip, p_mem_info);
    }

    return DRV_E_NONE;
}


int32
drv_usw_ftm_table_id_2_mem_id(uint8 lchip, uint32 tbl_id, uint32 tbl_idx, uint32* p_mem_id, uint32* p_offset)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_table_id_2_mem_id)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_table_id_2_mem_id(lchip, tbl_id, tbl_idx, p_mem_id, p_offset);
    }

    return DRV_E_NONE;
}

int32
drv_usw_get_memory_size(uint8 lchip, uint32 mem_id, uint32*p_mem_size)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_memory_size)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_memory_size(lchip, mem_id, p_mem_size);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_cam_by_tbl_id(uint8 lchip, uint32 tbl_id, uint8* cam_type, uint8* cam_num)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_cam_by_tbl_id)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_cam_by_tbl_id(lchip, tbl_id, cam_type, cam_num);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_set_misc_config(uint8 lchip)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_set_misc_config)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_set_misc_config(lchip);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_adjust_flow_tcam(uint8 lchip, uint8 expand_key, uint8 compress_key)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_adjust_flow_tcam)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_adjust_flow_tcam(lchip, expand_key, compress_key);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_adjust_mac_table(uint8 lchip, drv_ftm_profile_info_t* p_profile)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_adjust_mac_table)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_adjust_mac_table(lchip, p_profile);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_reset_tcam_table(uint8 lchip)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_reset_tcam_table)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_reset_tcam_table(lchip);
    }

    return DRV_E_NONE;
}

int32
drv_usw_get_dynamic_ram_couple_mode(uint8 lchip, uint16 sram_type, uint32* couple_mode)
{
    DRV_INIT_CHECK(lchip);
    if(sram_type >= DRV_FTM_SRAM_TBL_MAX)
    {
        return DRV_E_INVALID_MEM;
    }
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_dynamic_ram_couple_mode)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_dynamic_ram_couple_mode(lchip, sram_type, couple_mode);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_tcam_tbl_info_detail(uint8 lchip, char* p_tbl_name)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_tcam_tbl_info_detail)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_tcam_tbl_info_detail(lchip, p_tbl_name);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_tcam_memory_info(uint8 lchip, uint32 mem_id, uint32* p_mem_addr, uint32* p_entry_num, uint32* p_entry_size, drv_ftm_tcam_info_t* tcam_info)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_tcam_memory_info)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_tcam_memory_info(lchip, mem_id, p_mem_addr, p_entry_num, p_entry_size, tcam_info);
    }

    return DRV_E_NONE;
}

uint32
drv_usw_ftm_memid_2_table(uint8 lchip, uint32 mem_id)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_memid_2_table)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_memid_2_table(lchip, mem_id);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_sram_tbl_id(uint8 lchip, uint32 sram_type, uint32* p_sram_tbl_id, uint8* p_share_num, uint8* p_per_tbl_entry_num)
{
    DRV_INIT_CHECK(lchip);
    if(sram_type >= DRV_FTM_SRAM_TBL_MAX)
    {
        return DRV_E_INVALID_MEM;
    }
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_sram_tbl_id)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_sram_tbl_id(lchip, sram_type, p_sram_tbl_id, p_share_num, p_per_tbl_entry_num);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_mplshash_mode(uint8 lchip, uint8* is_mpls)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_mplshash_mode)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_mplshash_mode(lchip, is_mpls);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_flow_stats_table_id(uint8 lchip, uint8 ram_idx, uint32* table_id)
{
    DRV_INIT_CHECK(lchip);
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_flow_stats_table_id)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_flow_stats_table_id(lchip, ram_idx, table_id);
    }

    return DRV_E_NONE;
}


int32
drv_usw_ftm_dump_table_info(uint8 lchip, uint32 tbl_id)
{
    uint8 blk_id = 0;

    if ( (NULL == TABLE_INFO_PTR(lchip, tbl_id)) || 0 == TABLE_FIELD_NUM(lchip, tbl_id))
    {
        DRV_FTM_DBG_OUT("Empty table:%d\r\n", tbl_id);
        return 0;
    }

    DRV_FTM_DBG_OUT("%-20s:%10s\n", "Name", TABLE_NAME(lchip, tbl_id));
    DRV_FTM_DBG_OUT("%-20s:0x%lx\n", "DataBase", TABLE_DATA_BASE(lchip, tbl_id, 0));
    DRV_FTM_DBG_OUT("%-20s:%d\n", "MaxIndex", TABLE_MAX_INDEX(lchip, tbl_id));
    DRV_FTM_DBG_OUT("%-20s:%d\n", "EntrySize", TABLE_ENTRY_SIZE(lchip, tbl_id));

    if (NULL == TABLE_EXT_INFO_PTR(lchip, tbl_id))
    {
        return 0;
    }

    if (TABLE_EXT_INFO_TYPE(lchip, tbl_id) == EXT_INFO_TYPE_DYNAMIC ||
        TABLE_EXT_INFO_TYPE(lchip, tbl_id) == EXT_INFO_TYPE_MIXED)
    {
        DRV_FTM_DBG_OUT("%-20s:%d\n", "ExtType", TABLE_EXT_INFO_TYPE(lchip, tbl_id));
        DRV_FTM_DBG_OUT("%-20s:0x%x\n", "Bitmap", DYNAMIC_BITMAP(lchip, tbl_id)[0]);
        for (blk_id = 0; blk_id < 32; blk_id++)
        {
            uint32 mem_id = 0;
            if (!DRV_IS_BIT_SET(DYNAMIC_BITMAP(lchip, tbl_id)[0], blk_id))
            {
                continue;
            }

            mem_id = (TABLE_EXT_INFO_TYPE(lchip, tbl_id) == EXT_INFO_TYPE_MIXED)? blk_id+DRV_FTM_MIXED0:blk_id;
            if(mem_id >= MAX_DRV_BLOCK_NUM)
            {
                continue;
            }
            DRV_FTM_DBG_OUT("\n==================================================\n");
            DRV_FTM_DBG_OUT("%-20s:%d\n", "BlkId", mem_id);
            DRV_FTM_DBG_OUT("%-20s:0x%x\n", "DataBase", DYNAMIC_DATA_BASE(lchip, tbl_id, mem_id, 0));
            DRV_FTM_DBG_OUT("%-20s:%d\n", "EntryNumber", DYNAMIC_ENTRY_NUM(lchip, tbl_id, mem_id));
            DRV_FTM_DBG_OUT("%-20s:%d\n", "StartIndex", DYNAMIC_START_INDEX(lchip, tbl_id, mem_id));
            DRV_FTM_DBG_OUT("%-20s:%d\n", "EndIndex", DYNAMIC_END_INDEX(lchip, tbl_id, mem_id));
        }
    }
    else if(TABLE_EXT_INFO_TYPE(lchip, tbl_id) == EXT_INFO_TYPE_TCAM ||
        TABLE_EXT_INFO_TYPE(lchip, tbl_id) == EXT_INFO_TYPE_TCAM_AD ||
    TABLE_EXT_INFO_TYPE(lchip, tbl_id) == EXT_INFO_TYPE_TCAM_LPM_AD ||
    TABLE_EXT_INFO_TYPE(lchip, tbl_id) == EXT_INFO_TYPE_TCAM_NAT_AD ||
    TABLE_EXT_INFO_TYPE(lchip, tbl_id) == EXT_INFO_TYPE_LPM_TCAM_IP)
    {

        DRV_FTM_DBG_OUT("%-20s:%x\n", "keySize", TCAM_EXT_INFO_PTR(lchip, tbl_id)->key_size);
        DRV_FTM_DBG_OUT("%-20s:%x\n", "KeyType", TCAM_KEY_TYPE(lchip, tbl_id));
        DRV_FTM_DBG_OUT("%-20s:%x\n", "KeyModule", TCAM_KEY_MODULE(lchip, tbl_id));
        DRV_FTM_DBG_OUT("%-20s:%x\n", "Bitmap", TCAM_BITMAP(lchip, tbl_id)[0]);
        for (blk_id = 0; blk_id < 32; blk_id++)
        {
            if (!DRV_BMP_ISSET(TCAM_BITMAP(lchip, tbl_id), blk_id))
            {
                continue;
            }
            DRV_FTM_DBG_OUT("\n==================================================\n");
            DRV_FTM_DBG_OUT("%-20s:%d\n", "BlkId", blk_id);
            DRV_FTM_DBG_OUT("%-20s:0x%x\n", "DataBase", TCAM_DATA_BASE(lchip, tbl_id, blk_id, 0));
            DRV_FTM_DBG_OUT("%-20s:0x%x\n", "MaskBase", TCAM_MASK_BASE(lchip, tbl_id, blk_id, 0));

            DRV_FTM_DBG_OUT("%-20s:%d\n", "EntryNumber", TCAM_ENTRY_NUM(lchip, tbl_id, blk_id));
            DRV_FTM_DBG_OUT("%-20s:%d\n", "StartIndex", TCAM_START_INDEX(lchip, tbl_id, blk_id));
            DRV_FTM_DBG_OUT("%-20s:%d\n", "EndIndex", TCAM_END_INDEX(lchip, tbl_id, blk_id));
        }
    }


  return 0;
}

uint8
drv_usw_ftm_sram_use_sdb(uint8 lchip, uint8 ram_id)
{
    if (DRV_MCHIP_FTM_API(lchip)->ftm_sram_get_sdb_en)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_sram_get_sdb_en(lchip, ram_id);
    }
    return FALSE;
}

int32
drv_usw_ftm_ram_with_chip_op(uint8 lchip, uint8 ram_id)
{
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_ram_with_chip_op)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_ram_with_chip_op(lchip, ram_id);
    }
    return FALSE;
}

int32
drv_usw_ftm_reset_dynamic_table(uint8 lchip)
{
    if (DRV_MCHIP_FTM_API(lchip)->ftm_reset_dynamic_table)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_reset_dynamic_table(lchip);
    }
    return FALSE;
}
int32
drv_usw_ftm_alloc_tcam(uint8 lchip, uint8 start_key_type, uint8 end_key_type, uint8 force_realloc)
{
    if (DRV_MCHIP_FTM_API(lchip)->ftm_alloc_tcam)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_alloc_tcam(lchip, start_key_type, end_key_type, force_realloc);
    }
    return FALSE;
}

int32
drv_usw_ftm_get_lpm_tcam_init_size(uint8 lchip, uint8 lpm_model, uint32 (*lpm_tcam_init_bmp)[3], drv_ftm_info_detail_t* p_ftm_info)
{
    uint16 mem_idx;
    uint16 mem_id;
    uint16 max_mem_id_a[3] = {0xFFFF,0xFFFF,0xFFFF};

    for (mem_idx = DRV_FTM_LPM_TCAM_KEY0; mem_idx < (DRV_FTM_LPM_TCAM_KEY0 + DRV_CONST(DRV_MAX_LPM_TCAM_NUM)); mem_idx++)
    {
        mem_id = mem_idx - DRV_FTM_LPM_TCAM_KEY0;
        if (DRV_IS_BIT_SET(lpm_tcam_init_bmp[0][0], mem_id))
        {
            max_mem_id_a[0] = mem_id;
        }
        if (DRV_IS_BIT_SET(lpm_tcam_init_bmp[0][1], mem_id))
        {
            max_mem_id_a[1] = mem_id;
        }
        if (DRV_IS_BIT_SET(lpm_tcam_init_bmp[0][2], mem_id))
        {
            max_mem_id_a[2] = mem_id;
        }
    }
    p_ftm_info->l3.lpm_tcam_init_size[0][0] = DRV_FTM_INIT_LPM_SIZE(lchip,max_mem_id_a[0],DsLpmTcamIpv4HalfKey_t);
    p_ftm_info->l3.lpm_tcam_init_size[0][1] = DRV_FTM_INIT_LPM_SIZE(lchip,max_mem_id_a[1],DsLpmTcamIpv4HalfKey_t);
    p_ftm_info->l3.lpm_tcam_init_size[0][2] = DRV_FTM_INIT_LPM_SIZE(lchip,max_mem_id_a[2],DsLpmTcamIpv4HalfKey_t);

    if(lpm_model == LPM_MODEL_PUBLIC_IPDA_PRIVATE_IPDA_HALF
       || lpm_model == LPM_MODEL_PUBLIC_IPDA_IPSA_PRIVATE_IPDA_IPSA_HALF)
    {
        sal_memset(max_mem_id_a, 0xFF, sizeof(max_mem_id_a));
        for (mem_idx = DRV_FTM_LPM_TCAM_KEY0; mem_idx < (DRV_FTM_LPM_TCAM_KEY0 + DRV_CONST(DRV_MAX_LPM_TCAM_NUM)); mem_idx++)
        {
            mem_id = mem_idx - DRV_FTM_LPM_TCAM_KEY0;
            if (DRV_IS_BIT_SET(lpm_tcam_init_bmp[1][0], mem_id))
            {
                max_mem_id_a[0] = mem_id;
            }
            if (DRV_IS_BIT_SET(lpm_tcam_init_bmp[1][1], mem_id))
            {
                max_mem_id_a[1] = mem_id;
            }
            if (DRV_IS_BIT_SET(lpm_tcam_init_bmp[1][2], mem_id))
            {
                max_mem_id_a[2] = mem_id;
            }
        }
        p_ftm_info->l3.lpm_tcam_init_size[1][0] = DRV_FTM_INIT_LPM_SIZE(lchip,max_mem_id_a[0],DsLpmTcamIpv4DaPubHalfKey_t);
        p_ftm_info->l3.lpm_tcam_init_size[1][1] = DRV_FTM_INIT_LPM_SIZE(lchip,max_mem_id_a[1],DsLpmTcamIpv4DaPubHalfKey_t);
        p_ftm_info->l3.lpm_tcam_init_size[1][2] = DRV_FTM_INIT_LPM_SIZE(lchip,max_mem_id_a[2],DsLpmTcamIpv4DaPubHalfKey_t);
    }
	return DRV_E_NONE;
}

int32
drv_usw_ftm_mapping_drv_hash_poly_type(uint8 lchip, uint8 sram_type, uint32 type, uint32* p_poly)
{
    if (DRV_MCHIP_FTM_API(lchip)->ftm_mapping_drv_hash_poly_type)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_mapping_drv_hash_poly_type(lchip, sram_type, type, p_poly);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_current_hash_poly_type(uint8 lchip, uint32 mem_id, uint8 sram_type, uint32 *poly_type)
{
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_current_hash_poly_type)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_current_hash_poly_type(lchip, mem_id, sram_type, poly_type);
    }

    return DRV_E_NONE;
}

int32
drv_usw_ftm_get_hash_poly_cap(uint8 lchip, uint8 sram_type, uint32 mem_id, uint8* poly_num, uint32* poly_type)
{
    if (DRV_MCHIP_FTM_API(lchip)->ftm_get_hash_poly_cap)
    {
        return DRV_MCHIP_FTM_API(lchip)->ftm_get_hash_poly_cap(lchip, sram_type, mem_id, poly_num, poly_type);
    }

    return DRV_E_NONE;
}
